package pacote;

import java.util.HashMap;

public class CacheL1 extends Memoria{
	
	private static final CacheL1 cachel1 = new CacheL1();
	private long tag;
	private Conjunto conjuntoAtual;
	private int numerodeConjuntos;
	private int offset;
	private int numerovias;
	private int tamanhobloco;
	
	public CacheL1(){
		
		
	}
	
	public void inicializarConjuntosL1(int tamanhoCacheL1KB, int numerovias, int tamanhobloco){
		this.tamanhobloco = tamanhobloco;
		this.setOffset((int)(Math.log10(this.getTamanhobloco())/Math.log10(2)));
		this.numerodeConjuntos = (int)(tamanhoCacheL1KB*1024)/(tamanhobloco*numerovias);
		this.numerovias = numerovias;
		setConjuntos(new HashMap<Integer,Conjunto>());
		for(int i = 0; i<this.getNumerodeConjuntos(); i++){
			getConjuntos().put(i, new Conjunto(this.getNumerovias(),i));
		}
		
	}
	
	@Override
	public boolean busca(long endereco) {
		this.setTag(endereco/((int)Math.pow(2,getOffset())));
		//System.out.println("Tag na cache l1: "+getTag());		
		setConjuntoAtual(getConjuntos().get((int)getTag()%this.getNumerodeConjuntos()));
		//System.out.println("conjunto pego: "+getTag()%this.getNumerodeConjuntos());
		//System.out.println(getConjuntoAtual()==null);
		if(getConjuntoAtual().contem(endereco/((int)Math.pow(2,getOffset())))){
			//Contabilidade.incrementarAcertosL1(); 	// acho que nao incrementa acessos neste pto, somente em L1.
			//Contabilidade.incrementarTempo(2);
			return true;
		}
		else{
			//this.carregarBloco(endereco);
			return false;
		}
	
	}

	@Override
	public void carregarBloco(long endereco) {
		Bloco bloco = new Bloco ();
		bloco.setOffsetBloco(offset);
		bloco.setEndBloco(endereco/((int)Math.pow(2,getOffset())));
		getConjuntoAtual().colocarBloco(bloco);
		// TODO Auto-generated method stub
		
	}

	public long getTag() {
		return tag;
	}

	public void setTag(long tag) {
		this.tag = tag;
	}

	public Conjunto getConjuntoAtual() {
		return conjuntoAtual;
	}

	public void setConjuntoAtual(Conjunto conjuntoAtual) {
		this.conjuntoAtual = conjuntoAtual;
	}
	public int getNumerodeConjuntos() {
		return numerodeConjuntos;
	}
	public int getOffset() {
		return offset;
	}
	public static CacheL1 getCachel1() {
		return cachel1;
	}

	public int getNumerovias() {
		return numerovias;
	}

	public int getTamanhobloco() {
		return tamanhobloco;
	}

	public void setOffset(int offset) {
		this.offset = offset;
	}
	
	

}
